﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Tedds_Tool.RulesBase;

namespace Tedds_Tool
{
    public class CS_Compiler
    {
        static readonly String[] dependencies = { "CommonInterfaces", "DynamicLoading", "Exceptions", "LEETCommon", "PlayBack", "StandardModuals", "Utilities" };
        private string tempdir = Path.Combine(Path.GetTempPath(), "TTTemps");

        private string testDLLPath;
        
        public CS_Compiler(String dllPath)
        {
            testDLLPath = dllPath;
        }

        public ICsCompilerResult Compile(String mainClass, string[] cSharpSource)
        {
            if (!File.Exists(testDLLPath))
            {
                throw new Exception("Test DLL Missing!");
            }

            string output = Path.Combine(tempdir, "Out.exe");
            string outassembly = Path.Combine(tempdir, "Runner.exe");
            if (File.Exists(outassembly)) File.Delete(outassembly);
            string file_name = Path.GetRandomFileName() + ".dll";

            if (!Directory.Exists(tempdir))
                Directory.CreateDirectory(tempdir);

            copyAllFiles();
            
            System.CodeDom.Compiler.CodeDomProvider cdp = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("CSharp");
            System.CodeDom.Compiler.CompilerParameters cpOut = getCodeDomCPout(outassembly, "LEET.Tests."+mainClass);
            System.CodeDom.Compiler.CompilerResults crOut = cdp.CompileAssemblyFromSource(cpOut, cSharpSource);

            return new CsCompilerResult(crOut);
        }

        /// <summary>
        /// Sets up the compiler parameters to create an executable file for the test runner.
        /// </summary>
        /// <returns>Returns the compiler parameters used in creating the executable code for the test runner.</returns>
        private System.CodeDom.Compiler.CompilerParameters getCodeDomCPout(string name, string mainfile)
        {
            System.CodeDom.Compiler.CompilerParameters cp = new System.CodeDom.Compiler.CompilerParameters();
            cp.GenerateExecutable = true;
            cp.GenerateInMemory = false;
            cp.OutputAssembly = name;
            cp.CompilerOptions = "/platform:x86";
            if (!string.IsNullOrEmpty(mainfile))
                cp.MainClass = mainfile;

            string temppath;
            foreach (String str in new String[] { "System", "WindowsBase", "UIAutomationClient", "UIAutomationTypes" })
            {
                temppath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
                @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\" + str + ".dll");
                if (!File.Exists(temppath))
                    temppath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
                        @"Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\" + str + ".dll");
                cp.ReferencedAssemblies.Add(temppath);
            }

            cp.ReferencedAssemblies.Add(testDLLPath);

            foreach (String file in dependencies)
            {
                String dll = "LEET." + file + ".dll";
                cp.ReferencedAssemblies.Add(Path.Combine(tempdir, dll));
            }

            return cp;
        }

        /// <summary>
        /// Copies all the required files to the compiled directory (temp folder).
        /// </summary>
        /// <param name="tests">A list of file names that need to be copied.</param>
        private void copyAllFiles()
        {
            foreach (String file in dependencies)
            {
                String dll = "LEET." + file + ".dll";
                String path = Path.Combine(tempdir, dll);
                if (File.Exists(path))
                    File.Delete(path);
                File.Copy(dll, path, true);
            }
        }
    }
}
